//-------------------------------------------------------------
// \project PluginCIMISS
// \file RequireDataFromCIMISS.java
// \author 刘意琮
// \date 2017-03-16
// \attention  cimiss里面用的世界时间 
// Copyright(c) 超图软件股份有限公司 气象事业部
// All Rights Reserved
// \version 1.0
//-------------------------------------------------------------
package com.mg.pluginpamiss;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;

import org.codehaus.jettison.json.JSONException;
import com.mg.cimiss.RestUtilDemo;
import com.mg.model.*;
import com.mg.pluginexample2.Model2;
import com.mg.pluginexample2.ModuleBase;

/**
 * 如果输入端或输出端可动态增删端口，需要派生端口类，否则Undo可能出错。
 */


public class RequireDataFromCIMISS extends ModuleBase {
    public RequireDataFromCIMISS(int nID) {
        super(nID);
        m_alOutputPort.add(new Port(this, Port.Type.Unknown));//输出字符串
        m_strResStyle = "json";
    }

    public String GetGroupName() {
        return "CIMISS";
    }

    public String GetName() {
        return "cimiss数据请求";
    }

    public String GetDescription() {
        return "";
    }

    public boolean OnAttach(Port portFrom, Port portTo) {
        try {
            int i = FindPort(portFrom, false);
            if (i != -1)
                return true;
            i = FindPort(portTo, true);
            if (i == -1)
                return false;
            if (portFrom.GetType() != portTo.GetType())
                return false;
            ArrayList<Param> alParam = new ArrayList<Param>();
            portFrom.GetModule().GetOutputParam(portFrom, alParam);
            if (alParam.size() < 2)
                return false;

        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

        return true;
    }

    public boolean OnDetach(Port portFrom, Port portTo) {
        if (!super.OnDetach(portFrom, portTo))
            return false;
        try {
            int i = FindPort(portTo, true);
            if (i == -1)
                return true;
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

    //用于 参数->XML 等
    public int GetParam(ArrayList<Param> alParam) {
        try {
            super.GetParam(alParam);
            //-------------------------------------------------------------------------------------------------------------------
            Model2 model = ((Model2) m_model);
            String strDatasources = model.GetWritableDatasources(true);
//        	if (m_strDSOutput.isEmpty() && !strDatasources.isEmpty())
//        		m_strDSOutput = strDatasources.split("\\|")[0];
            //-------------------------------------------------------------------------------------------------------------------

            alParam.add(new Param("Host", m_strHost, "地址", "xxx.xxx.xxx.xxx:xxxx", "CIMISS", Param.EditType.Default));
            alParam.add(new Param("UserID", m_strUserID, "用户名", "", "CIMISS", Param.EditType.Default));
            alParam.add(new Param("PassWord", m_strPassWord, "密码", "", "CIMISS", Param.EditType.Default));


            String sourseTableString = "SURF_CHN_MUL_DAY|SURF_CHN_MUL_TEN|SURF_CHN_MUL_MON|SURF_CHN_MUL_YER|SURF_CHN_MUL_HOR|";
            alParam.add(new Param("DataCode", m_strDataCode, "资料名称", "要查询的数据集", "数据源", Param.EditType.SelectOrInput, sourseTableString));
            alParam.add(new Param("DataCode", m_strResStyle, "返回方式", "何种格式返回", "数据源", Param.EditType.SelectOrInput, "json|csv"));
            String interfaceString = "statSurfEleInRegion|getSurfEleByTime|getSurfEleInRegionByTime|";
            alParam.add(new Param("TimeType", m_strInterface, "访问接口", "", "数据源", Param.EditType.SelectOrInput, interfaceString));


            alParam.add(new Param("Elements", m_strElements, "要素字段代码", "", "数据源", Param.EditType.Default));
            alParam.add(new Param("StatEles", m_strStatEles, "统计要素代码", "", "数据源", Param.EditType.Default));
            alParam.add(new Param("AdminCodes", m_strAdminCodes, "国内行政编码", "", "数据源", Param.EditType.Default));
            alParam.add(new Param("EleValueRanges", m_strEleValueRanges, "要素值范围", "多组以;隔开", "数据源", Param.EditType.Default));
            alParam.add(new Param("OtherParams", m_strOtherParams, "其他参数", "多组以;隔开", "数据源", Param.EditType.Default));
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return alParam.size();
    }

    public boolean OnParamChanged(ArrayList<Param> alParam, int nIndex, Object objValue) {
        return super.OnParamChanged(alParam, nIndex, objValue);
    }

    //用于 XML->参数 等
    public int SetParam(final ArrayList<Param> alParam) {
        int i = super.SetParam(alParam);
        try {
            m_strHost = (String) alParam.get(i++).m_objValue;
            m_strUserID = (String) alParam.get(i++).m_objValue;
            m_strPassWord = (String) alParam.get(i++).m_objValue;
            m_strDataCode = (String) alParam.get(i++).m_objValue;
            m_strResStyle = (String) alParam.get(i++).m_objValue;
            m_strInterface = (String) alParam.get(i++).m_objValue;
            m_strElements = (String) alParam.get(i++).m_objValue;
            m_strStatEles = (String) alParam.get(i++).m_objValue;
            m_strAdminCodes = (String) alParam.get(i++).m_objValue;
            m_strEleValueRanges = (String) alParam.get(i++).m_objValue;
            m_strOtherParams = (String) alParam.get(i++).m_objValue;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return i;
    }

    @SuppressWarnings("static-access")
    public boolean Execute() {
        //1参数读入，约束条件判断
        Model2 model = ((Model2) m_model);
        Calendar c = new GregorianCalendar();
        c.setTime(m_model.m_dateDataStart);
        c.add(Calendar.DATE, 1);//（鉴于建模工具里面有一个小时推移，取昨天数据方式是：前天的20时到昨天的20时）
        c.add(Calendar.HOUR, -8);

        String timeFormat = "";
        String startTime = "";
        String endTime = "";
        String m_strTimeType = "";
        String m_strMmutType = "";
        String str = "";
        String strValueOfYear = "1";//一年中的第几天，第几旬，第几候，第几月

        if (m_strDataCode.indexOf("MMUT") > -1)//历史资料
            m_strTimeType = "历史30年";
            //下面是常规值
        else if (m_strDataCode.contains("_HOR"))
            m_strTimeType = "小时";
        else if (m_strDataCode.contains("_DAY"))
            m_strTimeType = "日";
        else if (m_strDataCode.contains("_TEN"))
            m_strTimeType = "旬";
        else if (m_strDataCode.contains("_MON"))
            m_strTimeType = "月";
        else if (m_strDataCode.contains("_YER"))
            m_strTimeType = "年";

        //同步到世界时间  by 梁洪国
        Calendar cTemp = new GregorianCalendar();
//		cTemp.setTime(m_model.m_dateDataStart);
//		cTemp.add(Calendar.HOUR,-8);
//		m_model.m_dateDataStart = cTemp.getTime();
        cTemp.setTime(m_model.m_dateDataEnd);
        cTemp.add(Calendar.HOUR, -8);
        m_model.m_dateDataEnd = cTemp.getTime();

        timeFormat = "yyyyMMdd";//默认给到日的时间格式
        SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
        startTime = sdf.format(c.getTime());
        startTime += "000000";
        endTime = sdf.format(m_model.m_dateDataEnd);
        endTime += "000000";

        if (m_strTimeType.equals("旬")) {
            timeFormat = "yyyyMM";
            sdf = new SimpleDateFormat(timeFormat);
            str = sdf.format(c.getTime());
            sdf = new SimpleDateFormat("dd");
            int daytemp = Integer.parseInt(sdf.format(c.getTime()));
            if (daytemp < 11)
                str += "01000000";
            else if (daytemp < 21)
                str += "02000000";
            else {
                str += "03000000";
            }

            startTime = str;
            sdf = new SimpleDateFormat(timeFormat);
            str = sdf.format(m_model.m_dateDataEnd);
            sdf = new SimpleDateFormat("dd");
            daytemp = Integer.parseInt(sdf.format(m_model.m_dateDataEnd));
            if (daytemp < 11)
                str += "01000000";
            else if (daytemp < 21)
                str += "02000000";
            else {
                str += "03000000";
            }
            endTime = str;
        } else if (m_strTimeType.equals("小时")) {
            timeFormat = "yyyyMMddHH";
            sdf = new SimpleDateFormat(timeFormat);
            startTime = sdf.format(c.getTime());
            startTime += "0000";
            endTime = sdf.format(m_model.m_dateDataEnd);
            endTime += "0000";

        } else if (m_strTimeType.equals("日")) {
            timeFormat = "yyyyMMdd";
            sdf = new SimpleDateFormat(timeFormat);
            startTime = sdf.format(c.getTime());
            startTime += "000000";
            endTime = sdf.format(m_model.m_dateDataEnd);
            endTime += "000000";
        } else if (m_strTimeType.equals("月")) {
            timeFormat = "yyyyMM";
            sdf = new SimpleDateFormat(timeFormat);
            startTime = sdf.format(c.getTime());
            startTime += "01000000";
            endTime = sdf.format(m_model.m_dateDataEnd);
            endTime += "01000000";
        } else if (m_strTimeType.equals("年")) {
            timeFormat = "yyyy";
            sdf = new SimpleDateFormat(timeFormat);
            startTime = sdf.format(c.getTime());
            startTime += "0101000000";
            endTime = sdf.format(m_model.m_dateDataEnd);
            endTime += "0101000000";
        } else if (m_strTimeType.equals("历史30年")) {
            c.setTime(m_model.m_dateDataEnd);
            c.add(Calendar.HOUR, 8);
            if (m_strInterface.indexOf("Days") > -1) {
                m_strMmutType = "Days";
                strValueOfYear = String.valueOf(c.get(Calendar.DAY_OF_YEAR));
            } else if (m_strInterface.indexOf("Tens") > -1) {
                m_strMmutType = "Tens";
                c.add(Calendar.DATE, -1);//为了不想遇到临界值
                int month = c.get(Calendar.MONTH);
                System.out.println(c.getTime());
                strValueOfYear = String.valueOf(month * 3 + (c.get(Calendar.DATE) <= 10 ? 1 : (c.get(Calendar.DATE) <= 20 ? 2 : 3)));
            } else if (m_strInterface.indexOf("Months") > -1) {
                m_strMmutType = "Mons";
                c.add(Calendar.DATE, -1);
                strValueOfYear = String.valueOf(c.get(Calendar.MONTH) + 1);
            } else if (m_strInterface.indexOf("Pens") > -1) {
                m_strMmutType = "Pens";
                c.add(Calendar.DATE, -1);//为了不想遇到临界值
                int month = c.get(Calendar.MONTH);
                strValueOfYear = String.valueOf(month * 6 + (c.get(Calendar.DATE) <= 5 ? 1 : (c.get(Calendar.DATE) <= 10 ? 2 : (c.get(Calendar.DATE) <= 15 ? 3 :
                        (c.get(Calendar.DATE) <= 20 ? 4 : (c.get(Calendar.DATE) <= 25 ? 5 : 6))))));
            }
        }


        //2构造请求参数，并读取结果
        String[] times = null;//times就是获取的哪一天或者哪一个时间段的数据数据
        if (m_strInterface.contains("ByTimeRange")) {
            times = new String[2];
            times[0] = startTime;
            times[1] = endTime;
        } else if (m_strInterface.contains("ByTime")) {
            times = new String[1];
            times[0] = endTime;
        } else if (m_strInterface.contains("statSurfEleInRegion")) {
            times = new String[2];
            times[0] = startTime;
            times[1] = endTime;
        } else if (!m_strTimeType.equals("历史30年")) {
            model.OutputLog(Model.LogLevel.Error, "时间参数不合法：" + m_strInterface);
            return false;
        }

        model.OutputLog(Model.LogLevel.Info, "获取cimiss查询参数,提交请求");
        RestUtilDemo restUtilityDemo = new RestUtilDemo();
        restUtilityDemo.setHost(m_strHost);
        restUtilityDemo.setUserID(m_strUserID);
        restUtilityDemo.setPassWord(m_strPassWord);
        String params = "";
        try {
            model.OutputLog(Model.LogLevel.Info, m_strElements);
            if (!m_strTimeType.equals("历史30年")) {
                params = restUtilityDemo.getParams(m_strInterface, this.m_strDataCode, m_strElements.split(","), times, m_strAdminCodes, m_strResStyle, -1, null);
            } else {
                params = restUtilityDemo.getParams(m_strInterface, this.m_strDataCode, m_strElements.split(","), strValueOfYear, m_strMmutType, m_strAdminCodes, m_strResStyle, -1, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        params = restUtilityDemo.getStatParams(params, "", "", m_strEleValueRanges, m_strStatEles);
        params = restUtilityDemo.getOtherParams(params, m_strOtherParams);
        model.OutputLog(Model.LogLevel.Info, params);
        try {
            if (m_strResStyle.equalsIgnoreCase("json"))
                m_tableResultList = restUtilityDemo.getResutMapData(params);
            else {
                model.OutputLog(Model.LogLevel.Info, "PARAM:::" + params);
                if (!m_strTimeType.equals("历史30年")) {
                    m_listCSV = restUtilityDemo.GetResultCSV(params, true);
                } else {
                    m_listCSV = restUtilityDemo.GetResultCSV(params, false);
                }
            }


        } catch (JSONException e) {
            e.printStackTrace();
            model.OutputLog(Model.LogLevel.Error, "读取CIMISS内容出错");
            return false;
        }

        if (m_tableResultList == null && m_strResStyle.equalsIgnoreCase("json")) {
            model.OutputLog(Model.LogLevel.Error, "读取CIMISS结果为空" + restUtilityDemo.getErrorMessage());
            return false;
        } else if (m_listCSV == null) {
            model.OutputLog(Model.LogLevel.Error, "读取CIMISS结果为空" + restUtilityDemo.getErrorMessage());
            return false;
        }
        OnParamChanged();
        return true;
    }

    public int GetOutputParam(Port port, ArrayList<Param> alParam) {
        int i = FindPort(port, false);
        if (i == -1)
            return 0;
        if (m_strResStyle.equalsIgnoreCase("json"))
            alParam.add(new Param("ResultString", m_tableResultList));
        else if (m_strResStyle.equalsIgnoreCase("csv"))
            alParam.add(new Param("ResultString", m_listCSV));
        return alParam.size();
    }

    class ExpressionItem {
        ExpressionItem() {
            m_strOldTitle = "";
            m_strNewTitle = "";
            m_strCondition = "";
        }

        String m_strOldTitle;
        String m_strNewTitle;
        String m_strCondition;
    }

    //ArrayList<ExpressionItem> m_alExpressionItem;
    List<Map<String, Object>> m_tableResultList = null;
    List<String> m_listCSV = new ArrayList<String>();//要求第一行是字段名，第二行是数据类型，以下是数据（字段名中必须包含StationNum,x,y,Time字段）
    String m_strHost;
    String m_strUserID;
    String m_strPassWord;
    String m_strDataCode;
    String m_strInterface;
    String m_strElements;
    String m_strStatEles;
    String m_strAdminCodes;
    String m_strEleValueRanges;
    String m_strOtherParams;
    String m_strResStyle;
}

